<?php
define ( 'LIB', realpath ( dirname ( __FILE__ ) ) );
$__CONFIG = array ();
if (! defined ( 'ROOT' )) {
	define ( 'ROOT', realpath ( dirname ( __FILE__ ) . '/../' ) );
}
require_once dirname ( __FILE__ ) . '/exceptionext.class.php';

class Base {
	/**
	 * 配置文件参数
	 *
	 * @var array
	 */
	
	public static $aConf;
	/**
	 * 所有加载的对象
	 *
	 * @var array
	 */
	public static $aClass = array ();
	
	public static $aClassPath = array ();
	
	public static $aError = array ();
	
	public static $oBase;
	
	/**
	 * 初始化方法
	 *
	 * @param string $sConfigFile 配置文件名
	 */
	public static function init($sConfigFile = null) {
		global $__CONFIG;
		$sUrl = $_SERVER ['SERVER_PORT'] == 443 ? 'https://' : 'http://';
		$sUrl .= $_SERVER ['HTTP_HOST'];
		$sUrl .= $_SERVER ['SERVER_PORT'] != 80 && $_SERVER ['SERVER_PORT'] != 443 ? ':' . $_SERVER ['SERVER_PORT'] : '';
		define ( 'URL', $sUrl . $_SERVER ['REQUEST_URI'] );
		define ( 'EURL', urlencode ( URL ) );
		Base::$oBase = new Base ();
		session_start ();
		date_default_timezone_set ( 'PRC' );
		set_time_limit ( 0 );
		if ($sConfigFile) {
			Base::parseConfigFile ( $sConfigFile, true );
			if (! Base::getConf ( 'base.site_root' )) {
				if ($sConfigFile) {
					Base::setConf ( 'base.site_root', dirname ( realpath ( $sConfigFile ) ) );
				} else {
					Base::setConf ( 'base.site_root', ROOT );
				}
			}
			if (! Base::getConf ( 'base.site_url' )) {
				Base::setConf ( 'base.site_url', str_replace ( $_SERVER ['DOCUMENT_ROOT'], $sUrl, ROOT ) );
			}
		}
		Base::debug ();
	}
	
	public static function debug() {
		$sDebug = Base::getConf ( 'base.debug' );
		if ($sDebug == 'firefox') {
			require_once LIB . '/fb.php';
		} elseif ($sDebug == 'chrome') {
			require_once LIB.'/ChromePhp.php';
		}
	}
	
	/**
	 * 获取配置文件中的值
	 *
	 * @param string $sName
	 * @return string
	 */
	public static function getConf($sName, $sConfigFile = null) {
		if ($sConfigFile) {
			if (is_file ( $sConfigFile )) {
				$sConfId = md5 ( realpath ( $sConfigFile ) );
			} else {
				$sConfId = $sConfigFile;
			}
		} else {
			$sConfId = 'default';
		}
		
		list ( $sType, $sName ) = explode ( '.', $sName );
		if ($sName) {
			$sValue = Base::$aConf [$sConfId] [$sType] [$sName];
			if ($sValue == null) {
				$aParentValue = Base::$aConf [$sConfId] [$sType];
				if (is_array ( $aParentValue )) {
					$sValue = Base::parseConf ( $aParentValue, $sName );
				}
			}
			if ($sValue === null && $sConfId != 'default') {
				$sValue = Base::getConf ( $sType . '.' . $sName );
			}
			return $sValue;
		} else {
			return Base::$aConf [$sConfId] [$sType];
		}
	}
	
	public function setConf($sName, $sValue, $sConfigFile = null) {
		global $__CONFIG;
		if ($sConfigFile) {
			if (is_file ( $sConfigFile )) {
				$sConfId = md5 ( realpath ( $sConfigFile ) );
			} else {
				$sConfId = $sConfigFile;
			}
		} else {
			$sConfId = 'default';
		}
		
		list ( $sType, $sName ) = explode ( '.', $sName );
		Base::$aConf [$sConfId] [$sType] [$sName] = $sValue;
		
		if ($sConfId == 'default') {
			$__CONFIG = Base::$aConf ['default'];
		}
	}
	
	public static function parseConfigFile($sConfigFile = null, $bDefault = false, $sConfigId = null) {
		global $__CONFIG;
		if ($bDefault) {
			$sConfId = 'default';
		} else {
			if ($sConfigId) {
				$sConfId = $sConfigId;
			} else {
				$sConfId = md5 ( realpath ( $sConfigFile ) );
			}
		}
		if (is_file ( $sConfigFile )) {
			Base::$aConf [$sConfId] = parse_ini_file ( $sConfigFile, true );
			if ($sConfId == 'default') {
				$__CONFIG = Base::$aConf ['default'];
			}
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 实例化对象
	 * 如果该对象已经实例化，则返回已经实例化后的对象
	 *
	 * @param string $sClassName
	 * @return object
	 */
	public static function loadClass($sClassName, $sType = 'lib') {
		if ($sType == 'lib') {
			$sPath = LIB;
		} else {
			$sPath = Base::getClassPath ( $sType );
		}
		try {
			if (strpos ( $sClassName, '.' ) !== false) {
				$sClassName = substr ( $sClassName, strrpos ( '.', $sClassName ) + 1 );
			}
			$sClassFile = $sPath . '/' . strtolower ( $sClassName ) . '.class.php';
			if (! is_file ( $sClassFile )) {
				$sClassName .= ucfirst ( $sType );
				$sClassFile = $sPath . '/' . strtolower ( $sClassName ) . '.class.php';
			}
			if (! is_file ( $sClassFile )) {
				throw new ExceptionExt ( '类文件' . $sClassFile . '不存在' );
			}
			require_once $sClassFile;
			$sClassCode = $sType . '_' . $sClassName;
			
			if (! array_key_exists ( $sClassCode, Base::$aClass )) {
				Base::$aClass [$sClassCode] = new $sClassName ();
			}
		} catch ( ExceptionExt $e ) {
			$e->showError ( true );
		}
		
		return Base::$aClass [$sClassCode];
	}
	
	public static function loadFile($sFilename, $sType = 'lib') {
		if ($sType == 'lib') {
			$sPath = LIB;
		} else {
			$sPath = Base::getClassPath ( $sType );
		}
		try {
			if (strpos ( $sFilename, '.' ) !== false) {
				$sFilename = substr ( $sFilename, strrpos ( '.', $sFilename ) + 1 );
				$sFilename = $sPath . '/' . str_replace ( '.', '/', $sFilename );
			} else {
				$sFilename = $sPath . '/' . $sFilename . '.class.php';
			}
			if (! is_file ( $sFilename )) {
				throw new ExceptionExt ( '文件' . $sFilename . '不存在' );
			}
			require_once $sFilename;
		} catch ( ExceptionExt $e ) {
			$e->showError ( true );
		}
	}
	
	public static function getClassPath($sType, $sPath = null) {
		if ($sPath == null && Base::$aClassPath [$sType]) {
			return Base::$aClassPath [$sType];
		}
		$sPath = $sPath ? $sPath : Base::getConf ( 'base.' . $sType . '_path' );
		if ($sPath == null) {
			$sRealPath = realpath ( ROOT . '/' . $sType );
		} else {
			$sRealPath = realpath ( $sPath );
		}
		if (! $sRealPath) {
			$sRealPath = realpath ( ROOT . '/' . $sPath );
		}
		
		try {
			if (! $sRealPath) {
				throw new ExceptionExt ( '类文件' . $sPath . '不存在' );
			}
		} catch ( ExceptionExt $e ) {
			$e->showError ( true );
		}
		
		Base::$aClassPath [$sType] = $sRealPath;
		return $sRealPath;
	}
	
	public static function parseConf($aValue, $sName) {
		$aResult = null;
		foreach ( $aValue as $sKey => $sRow ) {
			$aMatch = array ();
			preg_match ( '/^' . $sName . '_{0,1}(\d+)$/i', $sKey, $aMatch );
			if (! empty ( $aMatch ) && $aMatch [1]) {
				$aResult [$aMatch [1]] = $sRow;
			}
		}
		return $aResult;
	}
	
	public static function getWebRelativePath($sPath) {
		if (realpath ( $sPath )) {
			$sPath = substr ( realpath ( $sPath ), strlen ( $_SERVER ['DOCUMENT_ROOT'] ) );
		} elseif (realpath ( ROOT . '/' . $sPath )) {
			$sPath = substr ( realpath ( ROOT . '/' . $sPath ), strlen ( $_SERVER ['DOCUMENT_ROOT'] ) );
		} else {
			$sPath = substr ( $sPath, strlen ( $_SERVER ['DOCUMENT_ROOT'] ) );
		}
		$sPath = str_replace ( DIRECTORY_SEPARATOR, '/', $sPath );
		if (substr ( $sPath, 0, 1 ) != '/') {
			$sPath = '/' . $sPath;
		}
		return $sPath;
	}
	
	public static function getSearch($sException = null) {
		if (is_array ( $_GET )) {
			$aGet = $_GET;
			if (is_array ( $sException )) {
				foreach ( $sException as $sKey => $sRow ) {
					if (is_string ( $sKey )) {
						$aGet [$sKey] = $sRow;
					} elseif ($sRow == null) {
						unset ( $aGet [$sKey] );
					} else {
						unset ( $aGet [$sRow] );
					}
				}
			} elseif ($sException) {
				unset ( $aGet [$sException] );
			}
			$aResult = array ();
			foreach ( $aGet as $sKey => $sRow ) {
				$aResult [] = $sKey . '=' . urlencode ( $sRow );
			}
			return implode ( '&', $aResult );
		} else {
			return '';
		}
	}
	
	public function getInputFromSearch($sException = null) {
		if (is_array ( $_GET )) {
			$aGet = $_GET;
			$sInput = null;
			if (is_array ( $sException )) {
				foreach ( $sException as $sKey => $sRow ) {
					if (is_string ( $sKey )) {
						$aGet [$sKey] = $sRow;
					} elseif ($sRow == null) {
						unset ( $aGet [$sKey] );
					} else {
						unset ( $aGet [$sRow] );
					}
				}
			} elseif ($sException) {
				unset ( $aGet [$sException] );
			}
			foreach ( $aGet as $sKey => $sRow ) {
				$sInput .= '<input type="hidden" name="' . $sKey . '" value="' . $sRow . '">';
			}
			return $sInput;
		} else {
			return '';
		}
	}
	
	public function __call($sName, $aArguments) {
		list ( $sClassName, $sMethod, $sClassType, $sType ) = explode ( '_', $sName );
		if (! $sClassType) {
			$sClassType = 'lib';
		}
		$aNewArgument = array ();
		foreach ( $aArguments as $sRow ) {
			if (is_string ( $sRow ) && strpos ( $sRow, '$' ) === 0) {
				$aNewArgument [] = $sRow;
			} else {
				$aNewArgument [] = var_export ( $sRow, true );
			}
		}
		if (in_array ( $sType, array ('func', 'function' ) )) {
			Base::loadFile ( $sClassName, $sClassType );
			eval ( '$sResult =' . $sMethod . '(' . implode ( ', ', $aNewArgument ) . ');' );
		} else {
			$oObject = Base::loadClass ( $sClassName, $sClassType );
			eval ( '$sResult = $oObject->' . $sMethod . '(' . implode ( ', ', $aNewArgument ) . ');' );
		}
		return $sResult;
	}
	
	/**
	 * 显示提示信息页面
	 *
	 * @param array $aMessage 每条显示一行
	 * @param array $aUrl key跳转名称 value跳转地址 第一个是默认跳转地址
	 * @param string $sType error warning normal
	 * @param int $iTimeout 毫秒
	 */
	public static function showMessage($aMessage, $aUrl = null, $sType = 'normal', $iTimeout = 3000) {
		if (is_array ( $aMessage )) {
			Base::$oBase->template_assign ( 'message', $aMessage );
		} else {
			Base::$oBase->template_assign ( 'message', array ($aMessage ) );
		}
		Base::$oBase->template_assign ( 'type', $sType );
		if (is_array ( $aUrl )) {
			Base::$oBase->template_assign ( 'url', $aUrl );
			$aValue = array_values ( $aUrl );
			$sUrl = $aValue [0];
		} elseif ($aUrl) {
			Base::$oBase->template_assign ( 'url', array ('立即跳转' => $aUrl ) );
			$sUrl = $aUrl;
		}
		if ($iTimeout && $sUrl) {
			if (is_int ( $sUrl )) {
				Base::$oBase->template_assign ( 'timeout', 'setTimeout(function(){history.go(-' . $sUrl . ')}, ' . $iTimeout . ');' );
			} else {
				Base::$oBase->template_assign ( 'timeout', 'setTimeout(function(){location="' . $sUrl . '"}, ' . $iTimeout . ');' );
			}
		}
		Base::$oBase->template_output ( 'message.html' );
		exit ();
	}
	
	public static function location($sUrl) {
		header ( 'location:' . $sUrl );
		exit ();
	}
}
?>